﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DlrBasic.Runtime
{
    /// <summary>
    /// Contains current state of BASIC excution context.
    /// </summary>
    public class DlrBasicState
    {
        int currentStatement;
        bool noCache = true;
        int lineNumber;
        int lineStatement;
        string statementName;

        public int CurrentStatement
        {
            get { return currentStatement; }
            set { currentStatement = value; noCache = true; }
        }

        public int LineNumber
        {
            get
            {
                ValidateCache();
                return lineNumber;
            }
        }

        public int LineStatement
        {
            get
            {
                ValidateCache();
                return lineStatement;
            }
        }

        public string StatementName
        {
            get
            {
                ValidateCache();
                return statementName;
            }
        }

        public bool IsStopped
        {
            get { return currentStatement < 0; }
        }

        StatementCallback statementCallback;

        public StatementCallback StatementCallback
        {
            get { return statementCallback; }
        }

        DlrBasicMemory memory;

        public DlrBasicMemory Memory
        {
            get { return memory; }
        }

        DlrBasicForStack forStack;

        public DlrBasicForStack ForStack
        {
            get { return forStack; }
        }

        DlrBasicGosubStack gosubStack;

        public DlrBasicGosubStack GosubStack
        {
            get { return gosubStack; }
        }

        DlrBasicUserFunctions userFunctions;

        public DlrBasicUserFunctions UserFunctions
        {
            get { return userFunctions; }
        }

        DlrBasicDebugInfo debugInfo;

        public DlrBasicDebugInfo DebugInfo
        {
            get { return debugInfo; }
        }

        public DlrBasicState(StatementCallback statementCallback,
            DlrBasicMemory memory, DlrBasicForStack forStack, DlrBasicGosubStack gosubStack,
            DlrBasicUserFunctions userFunctions, DlrBasicDebugInfo debugInfo, int currentStatement)
        {
            this.statementCallback = statementCallback;
            this.memory = memory;
            this.forStack = forStack;
            this.gosubStack = gosubStack;
            this.userFunctions = userFunctions;
            this.debugInfo = debugInfo;
            this.currentStatement = currentStatement;
            this.noCache = true;
        }

        private void ValidateCache()
        {
            if (IsStopped) 
                throw new InvalidOperationException("Debug information is not available");

            if (noCache)
            {
                debugInfo.GetLineNumberAndOffset(CurrentStatement, out lineNumber, out lineStatement);
                statementName = debugInfo.GetStatementName(CurrentStatement);
                noCache = false;
            }
        }
    }
}
